Viewpager на портрете и две панели на ландшафте - PullRequest
0 голосов
/ 28 мая 2018

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

Итак, я создал два разных файла макета, один из которых содержит толькоViewPager, другой с LinearLayout, а другой с двумя FrameLayout, я не думаю, что нужно показывать их здесь.Существует также логическое значение hasTwoPanes для двух конфигураций.

@Inject FragmentOne fragmentOne;
@Inject FragmentTwo fragmentTwo;

@Override
protected void onCreate(Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.activity_main);

    FragmentManager fm = getSupportFragmentManager();
    boolean hasTwoPanes = getResources().getBoolean(R.bool.hasTwoPanes);

    TabLayout tabLayout = findViewById(R.id.tab_layout);
    ViewPager viewPager = findViewById(R.id.view_pager);
    if (hasTwoPanes) {
        tabLayout.setVisibility(View.GONE);
    } else {
        tabLayout.setVisibility(View.VISIBLE);
        tabLayout.setupWithViewPager(viewPager);
        viewPager.setAdapter(new MyPagerAdapter(fm));
    }

    FragmentOne frag1 = (FragmentOne) fm.findFragmentByTag(getFragmentName(0));
    if (frag1 != null) fragmentOne = frag1;

    FragmentTwo frag2 = (FragmentTwo) fm.findFragmentByTag(getFragmentName(1));
    if (frag2 != null) fragmentTwo = frag2;

    if (hasTwoPanes) {
        if (frag1 != null) {
            fm.beginTransaction().remove(fragmentOne).commit();
            fm.beginTransaction().remove(fragmentTwo).commit();
            fm.executePendingTransactions();
        }

        fm.beginTransaction().add(R.id.frame_frag1, fragmentOne, getFragmentName(0)).commit();
        fm.beginTransaction().add(R.id.frame_frag2, fragmentTwo, getFragmentName(1)).commit();
    }
}

private class MyPagerAdapter extends FragmentPagerAdapter {

    MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        if (position == 0) {
            return fragmentOne;
        } else {
            return fragmentTwo;
        }
    }

    @Override
    public int getCount() {
        return 2;
    }

}

private static String getFragmentName(int pos) {
    return "android:switcher:" + R.id.view_pager + ":" + pos;
}

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

Поскольку адаптер пейджера представления дает имя своим фрагментам, мне нужно знать это имя (следовательно,getFragmentName(int pos) метод), чтобы вернуть этот фрагмент после поворота.

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

Чтобы прояснить ситуацию, это происходит в Деятельности, родительского фрагмента нет.Даже если фрагменты не показаны, фрагмент называется onViewCreated.Пейджер представления, кажется, правильно восстанавливает ссылки фрагмента в instantiateItem.Кроме того, при отладке фрагменты имеют значение added, равное true, и hidden, равное false.Это создает впечатление рендеринга в пейджере вида.

  • Как заставить пейджер представления отображать мои фрагменты?
  • Есть ли лучший способ добиться желаемого поведения?

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Вы пытались использовать PagerAdapter вместо FragmentPagerAdapter?Вы получите лучший контроль над созданием и обработкой фрагментов.В противном случае вы не знаете, что делает FragmentPagerAdapter (он делает это для вас, но, вероятно, неправильно).

Вы можете перенести большую часть этой логики в этот класс, делая деятельность более чистой, и, вероятно, также решить ваши проблемы,

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

0 голосов
/ 06 июня 2018

Решение, которое я нашел, очень простое, переопределите getPageWidth в моем адаптере пейджера следующим образом:

@Override
public float getPageWidth(int position) {
    boolean hasTwoPanes = getResources().getBoolean(R.bool.hasTwoPanes);
    return hasTwoPanes ? 0.5f : 1.0f;
}

R.bool.hasTwoPanes - это логические ресурсы, доступные в конфигурации по умолчанию и values-land.Мое расположение одинаково для обеих конфигураций, а расположение вкладок просто скрыто в альбомной ориентации.

Восстановление фрагмента выполняется автоматически с помощью пейджера представления.

0 голосов
/ 05 июня 2018

Попробуйте это

Портрет XML:

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

    <android.support.design.widget.TabLayout
        android:id="@+id/tab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Пейзаж XML:

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <FrameLayout
        android:id="@+id/fragmentA"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <FrameLayout
        android:id="@+id/fragmentB"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

Активность Java:

package com.dev4solutions.myapplication;

import android.graphics.Point;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import com.dev4solutions.myapplication.fragment.FragmentA;
import com.dev4solutions.myapplication.fragment.FragmentB;

public class FragmentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Point point = new Point();
        getWindowManager().getDefaultDisplay().getSize(point);
        setContentView(R.layout.activity_frag);
        if (point.y > point.x) {
            TabLayout tabLayout = findViewById(R.id.tab);
            ViewPager viewPager = findViewById(R.id.pager);
            tabLayout.setupWithViewPager(viewPager);
            viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));

        } else {
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.fragmentA, new FragmentA())
                    .commit();
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.fragmentB, new FragmentB())
                    .commit();
        }
    }
}
...