简体   繁体   English

将片段添加到以编程方式生成的FrameLayout

[英]Add fragment to programmatically generated FrameLayout

I have inherited some code that requires a change in how it works. 我继承了一些代码,需要改变它的工作方式。 The original way didn't have the flexibility now required. 原始方式现在没有灵活性。

The application is a form generator, and hence has to create the UI on demand. 应用程序是表单生成器,因此必须按需创建UI。 This is Xamarin native, not Xamarin forms. 这是Xamarin原生,而不是Xamarin形式。

A FrameLayout for each form question is being created programmatically, added to the view, then a fragment is being added to this FrameLayout. 正在以编程方式创建每个表单问题的FrameLayout,添加到视图中,然后将一个片段添加到此FrameLayout。 All this is happening AFTER OnCreateView once the UI has been loaded to show a progress circle. 一旦加载了UI以显示进度循环,所有这一切都发生在OnCreateView之后。

After working through a bunch of exceptions, I have become stuck with the exception 经过一系列例外后,我已经陷入了异常

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

My guess is that the FrameLayout doesn't exist when the fragment is trying to be displayed. 我的猜测是,当试图显示片段时,FrameLayout不存在。

The exception occurs after the OnCreate() method runs after OnCreateView() completes. OnCreateView()完成后运行OnCreate()方法后发生异常。

I have not been able to find any code precedent for adding FrameLayouts programmatically with Fragments. 我无法找到以编程方式使用Fragments添加FrameLayouts的任何代码先例。

CODE Snippet 代码片段

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();

Any advice would be greatly appreciated. 任何建议将不胜感激。 Thanks. 谢谢。

Extended Explanation 扩展说明

It may be a bit much to put in everything it does, but will try and put in as much as I can. 放入它所做的一切可能会有点多,但会尝试尽可能多地投入。 The Hierarchy of the page is 页面的层次结构是

Activity -> FormFragment -> UploadFragment

So the parent of the UploadFragment is also a fragment, not the Activity. 所以UploadFragment的父级也是一个片段,而不是Activity。

Upload Fragment 上传片段

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

CODE

 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() Sets the values of the label, the events for the buttons, and the image (if exists) to the imageview. SetUpload()将标签的值,按钮的事件和图像(如果存在)设置为imageview。 It also deals with a few extra events to do with form event handling. 它还处理一些与表单事件处理有关的额外事件。 Stopping SetUpload() from running still has the exception occur. 停止运行SetUpload()仍会发生异常。

FormFragment FormFragment

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

CODE

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() Calls the method where formBuilderWorker.DoWork() exists OnResume()调用formBuilderWorker.DoWork()存在的方法

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

LoadForm() uses a Interface to tell the FormFragment to display a control. LoadForm()使用接口告诉FormFragment显示控件。 One of which is the UploadFragment. 其中一个是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());
            }
        }

This is cleaned code to remove as much irrelevant code as possible. 这是清理代码,以尽可能多地删除不相关的代码。 The code shown is the path the code in question moves through. 显示的代码是有问题的代码通过的路径。

I found the issue. 我发现了这个问题。 Part of what I took out of the code above, was the Activity.RunOnUiThread() calls that add the frame to the main view. 我从上面的代码中取出的部分内容是Activity.RunOnUiThread()调用,它将框架添加到主视图中。 The issue was caused by Thread Timing. 问题是由线程计时引起的。 The UI thread was taking so long to add the frame to the view, that when the FragmentTransaction was trying to commit the changes, the frame still did not exist. UI线程需要很长时间才能将帧添加到视图中,当FragmentTransaction尝试提交更改时,框架仍然不存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 以编程方式将视图添加到以编程方式生成的视图 - Programmatically add views to a programmatically generated view 如何基于生成的代理 class 以编程方式添加 SOAP header - How to programmatically add a SOAP header based on a generated proxy class 以编程方式将新的Datagrid(或其他UserControll)添加到以编程方式生成的TabItem中(使用mvvm) - Programmatically add new Datagrid (or other UserControll) into a programmatically generated TabItem (using mvvm) Xamarin-将ESRI MapView动态添加到FrameLayout - Xamarin - Add ESRI MapView dynamically to FrameLayout 以编程方式生成控件的问题 - Problem with programmatically generated controls 以编程方式格式化生成的CodeDom代码 - Programmatically Format Generated CodeDom Code 关于以编程方式生成的控件的问题:”? - Question about programmatically generated controls:"? Xamarin Android FrameLayout在预期关闭应用程序的背面显示空白/空片段 - Xamarin Android FrameLayout displays blank/empty fragment on back where expected to close the app Android Xamarin以编程方式生成的Button单击 - Android Xamarin programmatically generated Button Click 在C#中设置以编程方式生成的程序集的描述 - Set description for programmatically generated assembly in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM