【问题标题】:Add fragment to programmatically generated FrameLayout将片段添加到以编程方式生成的 FrameLayout
【发布时间】:2019-05-07 22:02:35
【问题描述】:

我继承了一些需要更改其工作方式的代码。原来的方式没有现在所需的灵活性。

应用程序是一个表单生成器,因此必须按需创建 UI。这是 Xamarin 本机,而不是 Xamarin 形式。

正在以编程方式为每个表单问题创建一个 FrameLayout,将其添加到视图中,然后将一个片段添加到此 FrameLayout。一旦加载了 UI 以显示进度圈,所有这些都发生在 OnCreateView 之后。

在处理了一堆异常之后,我已经被异常卡住了

Java.Lang.IllegalArgumentException: No view found for id 0x50 (unknown) for fragment UploadFragment{a31e878 #7 id=0x50 upload_80}

我的猜测是当片段试图显示时 FrameLayout 不存在。

OnCreate() 方法在OnCreateView() 完成后运行后发生异常。

我还没有找到任何代码先例以通过 Fragments 以编程方式添加 FrameLayouts。

代码片段

frame = new FrameLayout(this.Context);
frame.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
upload = new Widgets.UploadFragment(control, binding, Inflater, a, xFormInstance);
MainFormLayout.AddView(frame);
frame.Id = control.id;
fragmentTx.Add(frame.Id, upload, $"upload_{control.id}");    
fragmentTx.Commit();

任何建议将不胜感激。谢谢。

扩展说明

把它所做的一切都投入其中可能有点多,但我会尽可能多地投入。 页面的层次结构是

Activity -> FormFragment -> UploadFragment

所以UploadFragment的父级也是一个fragment,而不是Activity。

上传片段

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
    <RelativeLayout>
        <LinearLayout>
            <TextView/>
            <ImageButton/>
        </LinearLayout>
        <ImageView/>
    </RelativeLayout>
</LinearLayout>

代码

 public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
        }

 public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            // Use this to return your custom view for this Fragment
            _inflater = inflater;
            v = _inflater.Inflate(Resource.Layout.BindImageInput, container, false);            
            SetUpload();
            return v;
            //return base.OnCreateView(inflater, container, savedInstanceState);
        }

SetUpload() 将标签的值、按钮的事件和图像(如果存在)设置为图像视图。它还处理一些与表单事件处理有关的额外事件。停止运行SetUpload() 仍然会发生异常。

表单片段

<RelativeLayout>
    <TextView />
    <View />
    <ScrollView>
        <LinearLayout />
    </ScrollView>
</RelativeLayout>

代码

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            ShowLoading();
            View v = inflater.Inflate(Resource.Layout.Form2, container, false);    
            MainFormLayout = v.FindViewById<LinearLayout>(Resource.Id.mainFormView);
            MainScrollView = v.FindViewById<ScrollView>(Resource.Id.mainScrollView);

            formBuilderWorker = new BackgroundWorker();
            return v;
        }

OnResume()调用formBuilderWorker.DoWork()所在的方法

formBuilderWorker.DoWork += delegate
{
    Form.LoadForm(null, this, FormInstance);
}

LoadForm() 使用接口告诉FormFragment 显示控件。其中之一是 UploadFragment。

public void AddControl(Controls control, int? sectionID)
        {
///CODE REMOVED FOR OTHER CONTROL TYPES (they still use old codebase)
            Bindings binding = XForm.GetBindingForControl(control, FormInstance);
            try
            {
                // Create a new fragment and a transaction.
                FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();    

                FrameLayout frame = null;    
                Widgets.UploadFragment upload = null;
                frame = new FrameLayout(this.Context);
                frame.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
                frame.Id = control.id;
                upload = new Widgets.UploadFragment(control, binding, Inflater, a, xFormInstance);                    
                MainFormLayout.AddView(frame);
                ControlViews.Add(frame);             
                fragmentTx.Replace(frame.Id, upload, $"upload_{control.id}");
                //fragmentTx.Show(upload);
                fragmentTx.Commit();


            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

这是清理代码以尽可能多地删除不相关的代码。显示的代码是相关代码移动的路径。

【问题讨论】:

  • 你能显示 UploadFragment 的代码吗?我用你的方式测试它,它有效。
  • 我刚刚添加了更多关于应用程序设置以及它们如何组合在一起的信息。对不起,代码/文本墙。
  • 我尝试在另一个片段中添加片段,类似于您在上面所做的,但它也可以,如果可能,您可以将您的项目更新到 github,然后可以更准确地找到错误

标签: c# android android-fragments xamarin


【解决方案1】:

我发现了问题。我从上面的代码中取出的部分内容是将框架添加到主视图的Activity.RunOnUiThread() 调用。该问题是由线程计时引起的。 UI 线程将框架添加到视图需要很长时间,以至于当 FragmentTransaction 尝试提交更改时,框架仍然不存在。

【讨论】:

    猜你喜欢
    • 2013-08-20
    • 2016-06-18
    • 1970-01-01
    • 2012-06-19
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多