Добавить фрагмент в программно сгенерированный FrameLayout - PullRequest
0 голосов
/ 08 мая 2019

Я унаследовал некоторый код, который требует изменения в том, как он работает.Оригинальный способ не обладал необходимой гибкостью.

Приложение является генератором форм и, следовательно, должно создавать пользовательский интерфейс по требованию.Это родной Xamarin, а не формы Xamarin.

FrameLayout для каждого вопроса формы создается программно, добавляется в представление, затем к этому FrameLayout добавляется фрагмент.Все это происходит ПОСЛЕ OnCreateView после загрузки пользовательского интерфейса для отображения круга выполнения.

После проработки нескольких исключений я застрял с исключением

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

Я предполагаю, что FrameLayout не существует, когда фрагмент пытается отображаться.

Исключение возникает после запуска метода OnCreate() после завершения OnCreateView().

Мне не удалось найти ни одного прецедента кода для программного добавления 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 также является фрагментом, а не 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() по-прежнему вызывает исключение.

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() Вызывает методгде 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());
            }
        }

Это очищенный код, позволяющий удалить как можно больше ненужного кода.Показанный код - это путь, по которому проходит рассматриваемый код.

1 Ответ

0 голосов
/ 13 мая 2019

Я нашел проблему. Частью того, что я вынул из приведенного выше кода, были Activity.RunOnUiThread() вызовы, которые добавляют фрейм к основному виду. Проблема была вызвана синхронизацией потоков. Поток пользовательского интерфейса занял так много времени, чтобы добавить фрейм в представление, и когда FragmentTransaction пытался зафиксировать изменения, фрейм все еще не существовал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...