Может ли фрагмент переключаться с Dialog на Embedded при вращении? - PullRequest
3 голосов
/ 11 февраля 2012

Итак, у меня есть фрагмент критериев поиска, в который можно вводить критерии поиска, и когда поиск выполняется, результаты поиска отображаются во фрагменте результатов поиска. В альбомной ориентации два фрагмента, естественно, могут отображаться рядом. Пока это просто реализовать.

В портретной ориентации и на телефоне я бы хотел, чтобы фрагмент Критерии поиска отображался как всплывающее диалоговое окно, а не рядом с результатами поиска. В разделе Выбор между диалогом или встраиванием в DialogFragment я вижу, что я могу либо встроить фрагмент, либо показать его в виде диалога. Это может сработать для меня, если не усложнит изменение ориентации.

Если я использую теги XML в макете для действия, я получаю все виды неприятностей, когда я изменяю ориентацию.

РЕДАКТИРОВАТЬ: Сегодня я решил попробовать и посмотреть, смогу ли я получить простой рабочий процесс, используя DialogFragment, переключающийся между отображением диалогового окна и встроенным в зависимости от ориентации устройства. Это оказывается довольно сложно, и я до сих пор не нашел что-то, что работает. Вот что у меня есть.

package org.nsdev.experiments;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class FragmentSearchTestActivity extends FragmentActivity
{
    private static SearchCriteriaFragment searchCriteriaFragment;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        View container = findViewById(R.id.search_criteria_container);

        android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

        if (searchCriteriaFragment == null)
        {
            searchCriteriaFragment = SearchCriteriaFragment.newInstance();
            searchCriteriaFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
        }

        android.support.v4.app.Fragment f = getSupportFragmentManager().findFragmentByTag("search_criteria");
        if (f != null)
        {
            ft.remove(f);
        }

        if (container == null)
        {
            searchCriteriaFragment.setCancelable(true);
            searchCriteriaFragment.setHasOptionsMenu(false);
            searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria");
        }
        else
        {
            ft.remove(searchCriteriaFragment);
            ft.add(R.id.search_criteria_container, searchCriteriaFragment, "search_criteria");
            ft.commit();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        if (item.getItemId() == R.id.menu_item_search)
        {
            searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria");
        }
        return super.onOptionsItemSelected(item);
    }
}

В частности, я не смог заставить что-либо работать, если не сохранил статическую копию SearchCriteriaFragment и повторно использовал ее всякий раз, когда onCreate вызывался в Activity. Это кажется мне очень неправильным.

SearchResultsFragment.java:

package org.nsdev.experiments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SearchResultsFragment extends android.support.v4.app.Fragment
{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.results, container);
    }

}

SearchCriteriaFragment.java:

package org.nsdev.experiments;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SearchCriteriaFragment extends android.support.v4.app.DialogFragment
{

    private static final String TAG = "SearchCriteriaFragment";
    View v;

    static SearchCriteriaFragment newInstance()
    {
        Log.e(TAG, "newInstance");
        SearchCriteriaFragment d = new SearchCriteriaFragment();
        return d;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        if (v == null)
        {
            v = inflater.inflate(R.layout.criteria, container, false);
        } 
        else
        {
            if (v.getParent() instanceof ViewGroup) 
            {
                Log.e(TAG, "Removing from viewgroup");
                ((ViewGroup)v.getParent()).removeAllViews();
            }
        }

        return v;
    }

}

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

Рез / макет / main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <fragment
        android:id="@+id/search_results"
        android:name="org.nsdev.experiments.SearchResultsFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

Рез / макет-земля / main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <FrameLayout
        android:id="@+id/search_criteria_container"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent" />

    <fragment
        android:id="@+id/search_results"
        android:layout_toRightOf="@+id/search_criteria_container"
        android:name="org.nsdev.experiments.SearchResultsFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

Вы можете видеть из этих двух схем, что я пытаюсь сделать. В обычной ориентации FrameLayout не существует, поэтому мы можем обнаружить это и показать вместо него DialogFragment. В противном случае мы можем встроить DialogFragment в FrameLayout.

Последние два макета, в которые я только что поместил заполнители для результатов и макетов критериев:

Рез / макет / criteria.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="#300F">

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="21dp"
        android:paddingRight="30dp"
        android:text="Test Criteria" />

</RelativeLayout>

Рез / макет / Results.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="#f00">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:text="Results"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

Я думал, что понял это, пока не начал вращать устройство и проверять флажок на устройстве ICS. Обратите внимание на то, что я установил полупрозрачный цвет фона для crit.xml RelativeLayout. Что я заметил, так это то, что в альбомной ориентации встроенный вид на самом деле сохранял старые версии вида, и они будут перекрываться новыми копиями вида каждый раз, когда я переключался в портретный режим и обратно. Это одна из причин, по которой я пытался сохранить только одну копию представления, возвращенного из onCreateView объекта SeachCriteriaFragment. Это не решает эту проблему.

Я могу сделать только один вывод: я, должно быть, поступаю неправильно. Я подозреваю, что структура Fragments никогда не была разработана для такого повторного использования фрагментов. Как я могу получить хорошее вращение, работающее, когда в Portrait я показываю DialogFragment в виде диалога, а в Landscape он встроен? Могу ли я заставить фреймворк делать что-то подобное более автоматически?

Я попытался установить searchCriteriaFragment.setRetainInstance (true), и весь ад развалился, поэтому я немедленно удалил эту строку.

Спасибо за любую помощь, чтобы вывести меня на правильный путь здесь.

1 Ответ

0 голосов
/ 11 февраля 2012

Я бы сказал так.

На телефоне сделайте SearchFormFragment активным и дайте ему диалог с темой.Тогда SearchResultsFragment также является отдельным самостоятельным действием.

XML-код SearchForm будет выглядеть следующим образом:

 <LinearLayout >
   <fragment class="com.your.package.ui.fragment.SearchFormFragment" />
 </LinearLayout>

Для получения темы диалога :

 <manifest . . . >
      <application . . . >
         <activity 
            android:name=".ui.phone.SearchFormFragmentActivity"
            android:theme="@android:style/Theme.Dialog" . . . >
         <activity 
            android:name=".ui.phone.SearchResultsFragmentActivity" . . . >

Это упрощает изменение ориентации с помощью onSaveInstanceState и onRestoreInstanceState и жизненного цикла действия.

Затем на планшете вы выполняете другое действие с двумя вашими фрагментами.

         <activity 
            android:name=".ui.tablet.SearchFragmentActivity" . . . >

SearchFragmentActivity.xml:

   <LinearLayout >
     <fragment class="com.your.pacakage.ui.fragment.SearchFormFragment"/>
     <fragment class="com.your.package.ui.fragment.SearchResultsFragment" />
   </LinearLayout>

Упрощено.

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