Xamarin Android - 当我第一次添加视图时,FrameLayout 只显示它的背景,但当我再次添加它时显示它

Xamarin Android - FrameLayout display only it's background when i add view first time, but displayed when i add it again

我有一个很奇怪的问题。我有一个自定义的 FrameLayout(它只有一个字符串 FileName 与 mvvmcross 和一些方法绑定)。 我用它在项目点击时显示媒体(Pdf、视频、声音和图片)。 我的项目是代表我的媒体文件并绑定到 mediaItems 的小图标。

当我点击这些图标之一时,当我到达断点时一切正常,framelyout 出现,但它只显示它的背景而不是它的子视图。

如果我缩小它并再次单击同一个项目,框架布局将再次出现并正确显示我的内容,我不知道为什么。

要了解其背后的逻辑,请查看其工作原理:

这是我的自定义框架布局 C# 代码:

public class MediaController : FrameLayout
{

    #region [ Fields ]
    private Context _context;
    private ImageController _imageController;
    private SoundAndVideoController _soundAndVideoController;
    private PdfController _pdfController;
    private LayoutInflater _layoutInflater;
    private readonly string[] supportedVideoFormat = { "mp4", "3gp", "mkv", "mpg" };
    private readonly string[] supportedPictureFormat = { "png", "bmp", "gif", "jpg" };
    private readonly string[] supportedAudioFormat = { "flac", "mp3", "wav" };
    private readonly string[] supportedPdfFormat = { "pdf" };
    #endregion
    #region [ Properties ]
    private string _fileName;
    public string FileName
    {
        get
        {
            return _fileName;
        }
        set
        {
            if (value != null)
            {
                _fileName = value;
                Init();
            }
        }
    }
    #endregion

    #region [ Constructors ]
    public MediaController(Activity activity) : base(activity)
    {
        _context = activity.BaseContext;
        Init();
    }

    public MediaController(Context context) : base(context)
    {
        _context = context;
        Init();
    }

    public MediaController(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        _context = context;
        Init();
    }

    public MediaController(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
        _context = context;
        Init();

    }

    public MediaController(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
    {
        _context = context;
        Init();
    }
    #endregion
    #region [ Methods ]
    public void InitViews()
    {

    }

    private void Init()
    {
        if (!string.IsNullOrEmpty(FileName) &&_context != null)
        {
            this.RemoveAllViews();
            string extension = FileName.Split('.').Last();
            _layoutInflater = (LayoutInflater)_context.GetSystemService(Context.LayoutInflaterService);
            if (supportedAudioFormat.Any(extension.ToLower().Contains) || supportedVideoFormat.Any(extension.ToLower().Contains))
            {
                InitMusicOrVideoPlayer(extension);
            }
            else if (supportedPictureFormat.Any(extension.ToLower().Contains))
            {
                InitImageViewer();
            }
            else if (supportedPdfFormat.Any(extension.ToLower().Contains))
            {
                InitPdfViewer();
            }
            else
            {
                //manage error;
            }
        }
    }

    private void InitMusicOrVideoPlayer(string fileExtension)
    {
        SurfaceView musicView = (SurfaceView)layoutInflater.Inflate(Resource.Layout.MusicVideoTemplate, null);

        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(this.Width, this.Height);

        this.AddView(musicView, layoutParams);

        if (supportedAudioFormat.Any(fileExtension.ToLower().Contains))
        {
            ImageView imageView = new ImageView(_context);

            imageView.Background = _context.GetDrawable(Resource.Drawable.speaker);

            imageView.SetScaleType(ImageView.ScaleType.FitCenter);
            layoutParams = new FrameLayout.LayoutParams(this.Width / 4, this.Height / 4);
            layoutParams.SetMargins((int)(this.Width * 0.375f), (int)(this.Height * 0.375f), 0, 0);
            this.AddView(imageView, layoutParams);
            soundAndVideoController = new SoundAndVideoController(musicView, FileName, _context, true);
        }
        else
        {
            soundAndVideoController = new SoundAndVideoController(musicView, FileName, _context, false);
        }
    }

    private void InitPdfViewer()
    {
        FrameLayout pdfContainer = (FrameLayout)_layoutInflater.Inflate(Resource.Layout.PdfTemplate, null);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(this.Width, this.Height);
        this.AddView(pdfContainer, layoutParams);
        _pdfController = new PdfController(FileName, pdfContainer, _context);
    }

    private void InitImageViewer()
    {
        FrameLayout mediaImageContainer = (FrameLayout)_layoutInflater.Inflate(Resource.Layout.MediaImageTemplate, null);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(this.Width, this.Height);
        this.AddView(mediaImageContainer, layoutParams);
        _imageController = new ImageController(FileName, mediaImageContainer);
    }

    #endregion
}

这是我的 xml,其中包含我的自定义框架布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/Black"
    local:MvxBind="Visibility  MustShowMedias, Converter=Visibility ">
    <LinearLayout
        android:orientation="horizontal"
        android:weightSum="1"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:id="@+id/MediaLeftLayout"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.05">
            <Button
                android:id="@+id/MediaPreviousButton"
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:layout_gravity="center"
                android:text="Previous" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/MediaCenterLayout"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.9"
            android:orientation="vertical"
            android:weightSum="1">
            <space
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="0.05" />
            <MyProject.Droid.Views.MediaControllers.MediaController
                android:id="@+id/MediaContainer"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="0.9"
                android:background="#FFFFFF"
                local:MvxBind="FileName SelectedMedia.Source">

            </MyProject.Droid.Views.MediaControllers.MediaController>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/MediaRightLayout"
            android:orientation="vertical"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.05">
            <Button
                android:id="@+id/MediaCloseButton"
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:textColor="#FF0000"
                android:text="X"
                local:MvxBind="Click CloseMediaWindowCommand" />
            <Button
                android:id="@+id/MediaNextButton"
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:layout_gravity="center"
                android:text="Next" />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>

我在 Android 开发方面还很陌生,我完全不知道为什么这不起作用。也许我的框架布局没有完全加载(这很奇怪,因为它包含在我的视图中)。我非常愿意接受任何关于这个问题的帮助!

谢谢

编辑: 好的,这里有一些更新:

编辑 2:

PS:抱歉我的英语很糟糕

好的,我终于解决了这个问题!

出于某些原因和一些我还不了解的 android 行为,我的视图在加载此视图之前已添加到我的自定义框架布局中。

所以我找到的解决方案是将 ViewTreeObserver 添加到我的自定义布局,然后将我的子视图加载到那里:

protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
    ViewTreeObserver vto = this.ViewTreeObserver;
    vto.AddOnGlobalLayoutListener(this);
    vto.GlobalLayout += (sender, args) =>
    {
        if (!_hasLoaded)
        {
            Init();
            _hasLoaded =true;
        }
    };
}