Ответ 1
Думаю, я решил.
Я добавил фрагмент в задний стек, а затем до закрытия активности снова выскочил, что фактически избавилось от него. Кажется, работает до сих пор.
Каков правильный способ обработки изменения ориентации при использовании фрагментов?
У меня есть ландшафтный макет, содержащий 2 фрагмента (созданный в коде FrameLayout
s). Когда я переключаюсь в портретный режим (макет которого содержит только один FrameLayout
, который содержит только левую панель), фрагмент правой руки больше не требуется.
Я получаю сообщение об ошибке:
E/AndroidRuntime(4519): Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f060085 for fragment myFragment{418a2200 #2 id=0x7f060085}
который предположил, что моя деятельность пытается повторно присоединить фрагмент, где он был до изменения ориентации, но поскольку представление, содержащее фрагмент, не существует в портретном режиме, возникает ошибка.
Я пробовал следующие методы hide/remove/detach, но все равно получаю ошибку. Каков правильный способ рассказать фрагмент, он больше не нужен и не пытается отображать?
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragholder2);
//rightPane is a framelayout that holds my fragment.
if (rightPane == null && f != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.hide(f); // This doesnt work
ft.remove(f); // neither does this
ft.detach(f); // or this
ft.commit;
}
}
Думаю, я решил.
Я добавил фрагмент в задний стек, а затем до закрытия активности снова выскочил, что фактически избавилось от него. Кажется, работает до сих пор.
Я столкнулся с той же проблемой, и я думаю, что понял другое решение. Это решение может быть лучше, потому что вам не нужно добавлять фрагмент в задний стек.
Удалите фрагмент правой стороны из вашей активности в Activity.onSaveInstanceState()
до, вызвав super.onSaveInstanceState()
. Это работает для меня:
public MyActivity extends Activity
{
@Override
public onCreate(Bundle state)
{
super.onCreate(state);
// Set content view
setContentView(R.layout.my_activity);
// Store whether this is a dual pane layout
mDualPane = findViewById(R.id.rightFragHolder) != null;
// Other stuff, populate the left fragment, etc.
.
.
.
if (mDualPane)
{
mRightFragment = new RightFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.rightFragHolder, mRightFragment);
ft.commit()
}
}
@Override
public void onSaveInstanceState(Bundle state)
{
if (mDualPane)
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.remove(mRightFragment);
ft.commit()
}
super.onSaveInstanceState(state);
}
private boolean mDualPane;
private Fragment mRightFragment;
}
Если вы сохраняете фрагмент, не пытайтесь его сохранить.
setRetainInstance(false)
вместо
setRetainInstance(true)
Обычно у вас будет два фрагмента (слева/справа), один основной вид активности и один вид действия контейнера для правого фрагмента (только при отображении на телефонных устройствах). Это описано в этой записи в блоге: API флагов Android 3.0
public class MyActivity extends FragmentActivity
implements MyListFragment.MyContextItemSelectedListener {
@Override
public void onCreate(final Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity);
}
// Callback from ListFragment
@Override
public void myContextItemSelected(final int action, final long id) {
if (action == R.id.men_show) {
processShow(id);
}
}
private void processShow(final long id) {
if (Tools.isXlargeLand(getApplicationContext())) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.right);
if (fragment == null ||
fragment instanceof MyEditFragment ||
(fragment instanceof MyShowFragment && ((MyShowFragment) fragment).getCurrentId() != id)) {
fragment = new MyShowFragment(id);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.right, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
}
} else {
Intent intent = new Intent();
intent.setClass(this, MyShowActivity.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1SHOW);
}
}
private static boolean isXlargeLand(final Context context) {
Configuration configuration = context.getResources().getConfiguration();
return (((configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) &&
configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
}
}
Если у вас есть действие с двумя панелями с левой и правой панелью, и одна из панелей (как правило, правая панель), как предполагается, не будет отображаться, когда устройство переключится в портретный режим, пусть Android сделает свое дело и воссоздает правильную панель, Но во время onCreateView правой панели первое, что вам нужно сделать, это проверить, доступен ли один из элементов макета, используемых панелью. Если это не так, удалите фрагмент с помощью FragmentManager и немедленно верните его:
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
View myView = getActivity().findViewById(R.id.myView);
if (myView == null)
{
FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
fragTransaction.remove(this);
fragTransaction.commit();
return null;
}
}
Android восстанавливает оба фрагмента во время вращения экрана. Но если вы добавите чек ниже в onCreateView(), это не даст вам проблем:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (container == null) {
// Currently in a layout without a container, so no
// reason to create our view.
return null;
}
// inflate view and do other stuff
}
Я взял это из блог разработчиков Android.
Вам больше не нужна эта активность, потому что фрагмент будет показан в строке. Таким образом, вы можете завершить работу
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// we are in landscape so you do not need this activity anymore
finish();
return;
}
if (savedInstanceState == null) {
// plugin right pane fragment
YourFragment frgm = new YourFragment();
getSupportFragmentManager().beginTransaction()
.add(..., frgm).commit();
}
}