У меня есть приложение для Android, которое существует довольно давно, и все работает как надо, кроме Android Oreo.Существует ViewPager с множеством разных типов фрагментов различной сложности каждый.Он ведет себя правильно (смахивание влево / вправо), значения также автоматически сохраняются при наборе текста, захвате изображения или выборе элементов из списка и т. Д. На Android O, когда я делаю горизонтальную фотографию (он воссоздает действие вместе со всем внутри)отображается правильно, и когда я проведу пальцем влево / вправо для нескольких фрагментов, они начинают казаться полностью пустыми, если я вернусь на исходную страницу (где я сделал фотографию), она также будет пустой и все фрагменты рядом с ней.
Я перепробовал все, но ничего не работает.Я проверил время жизни каждого типа фрагмента, и они правильно приостановлены / уничтожены / воссозданы / возобновлены, но они абсолютно пустые.
Один из моих фрагментов содержит поле подписи, которое требует ViewPager для предотвращения перемещения страниц во время рисования подписипоэтому я использую следующий пользовательский ViewPager:
public class LockableViewPager extends ViewPager {
private boolean mPagingEnabled;
public LockableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.mPagingEnabled = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return this.mPagingEnabled && super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return this.mPagingEnabled && super.onInterceptTouchEvent(event);
}
public void setPagingEnabled(boolean enabled) {
this.mPagingEnabled = enabled;
}
}
Этот LockableViewPager затем помещается в файл макета активности:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<my.somedomain.someapp.ui.LockableViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parametersPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/view_pager_indicator"/>
<my.somedomain.someapp.ui.CustomViewPagerIndicator
android:id = "@+id/view_pager_indicator"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="2dp"
app:delimiterSize = "8dp"
app:itemSize="10dp" />
</RelativeLayout>
Активность, которая обрабатывает ViewPagerвыглядит следующим образом:
public class EditParametersActivity extends FragmentActivity
implements ParameterInteractionEvents, TouchEventsListenerInterface {
private static final String TAG = "EditParametersActivity";
private static final String CLASS_NAME = EditParametersActivity.class.getName();
//...
private static ArrayList<RouteStructureParamListItem> mParamItems = new ArrayList<>();
private static ArrayList<VibValueInstancesItem> mParameterValueInstanceItems = new ArrayList<>();
//...
private FrameLayout mMainLayout;
private LockableViewPager mViewPager;
private ParametersPagerAdapter mPagerAdapter;
private CustomViewPagerIndicator mPageIndicator;
private int mCurrentPage = 0;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_parameters);
mToolbar = findViewById(R.id.toolbar);
setActionBar(mToolbar);
if (getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setDisplayShowHomeEnabled(true);
}
mRlLoading = findViewById(R.id.rlLoading);
mMainLayout = findViewById(R.id.main_layout);
mViewPager = findViewById(R.id.parametersPager);
mViewPager.setOffscreenPageLimit(3);
mPageIndicator = findViewById(R.id.view_pager_indicator);
Bundle args = savedInstanceState != null ? savedInstanceState : getIntent().getExtras();
mCurrentUser = args.getParcelable(ARG_CURRENT_USER);
mItem = args.getParcelable(ARG_ROUTE_DETAILS_ITEM);
mRouteListItem = args.getParcelable(ARG_ROUTE_LIST_ITEM);
if (args.containsKey(ARG_LIST_ITEM_POSITION)) {
mCurrentPage = args.getInt(ARG_LIST_ITEM_POSITION);
}
if (mRouteListItem != null && mRouteListItem.getRouteDesc() != null) {
setTitle(mRouteListItem.getRouteDesc());
}
mRlLoading.setVisibility(View.VISIBLE);
mToolbar.setSubtitle(mItem.getNodeDescription());
mDrawerLayout = findViewById(R.id.drawer_layout);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
//...
mBtnToggleParametersDrawer = findViewById(R.id.btnToggleParametersDrawer);
mBtnToggleParametersDrawer.setOnClickListener(view -> mDrawerLayout.openDrawer(Gravity.END));
mRvNavDrawerParameters = findViewById(R.id.rvNavDrawerParameters);
mRvNavDrawerParameters.setLayoutManager(new LinearLayoutManager(this));
mRvNavDrawerParameters.setNestedScrollingEnabled(false);
if (savedInstanceState != null) {
mParamItems = args.getParcelableArrayList(ARG_ROUTE_STRUCTURE_PARAM_LIST);
displayParameters();
mRlLoading.setVisibility(View.GONE);
} else {
// Load parameters from database
GetViewPagerDataTask routesTask = new GetViewPagerDataTask(this,
mCurrentUser, mRouteListItem.getAssignedInspectionID(),
mItem.getRouteStructureTaskID());
routesTask.getTask().continueWith(task -> {
if (task.isFaulted()) {
mRlLoading.setVisibility(View.GONE);
showSnackBar(mMainLayout, "Error loading structure parameters", true, Snackbar.LENGTH_SHORT);
} else {
mParamItems = task.getResult().mData;
displayParameters();
mRlLoading.setVisibility(View.GONE);
updateToolbarAndNavDrawer();
}
return null;
}, Task.UI_THREAD_EXECUTOR);
}
//...
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mCurrentPage = position;
updateToolbarAndNavDrawer();
Tools.hideSoftKeyboard(EditParametersActivity.this);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//...
outState.putInt(ARG_LIST_ITEM_POSITION, mCurrentPage);
outState.putParcelableArrayList(ARG_ROUTE_STRUCTURE_PARAM_LIST, mParamItems);
}
//...
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void displayParameters() {
mPagerAdapter = new ParametersPagerAdapter(
getSupportFragmentManager(), mParamItems, mCurrentUser, mToolbar.getTitle().toString(),
mToolbar.getSubtitle().toString());
mViewPager.setAdapter(mPagerAdapter);
mPageIndicator.setViewPager(mViewPager);
mViewPager.setCurrentItem(mCurrentPage, true);
//...
}
@Override
public void onShowSnackBar(String message, boolean isError, int duration) {
showSnackBar(mMainLayout, message, isError, duration);
}
@Override
public void onRequestViewPagerLock(boolean lock) {
mViewPager.setPagingEnabled(!lock);
if (lock && mDrawerLayout.isDrawerOpen(Gravity.END)) {
mDrawerLayout.closeDrawer(Gravity.END);
}
mBtnToggleParametersDrawer.setEnabled(!lock);
mSpnVibParamInstances.setEnabled(!lock);
}
@Override
public void setScrollEnabled(boolean enabled) {
mViewPager.setPagingEnabled(enabled);
}
@Override
public void onNavDrawerParameterItemClick(int position) {
mViewPager.setCurrentItem(position, true);
mDrawerLayout.closeDrawer(Gravity.END);
mCurrentPage = position;
//...
}
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.END)) {
mDrawerLayout.closeDrawer(Gravity.END);
} else {
super.onBackPressed();
}
}
}
FragmentStatePagerAdapter немного изменен для повышения производительности и может предоставить текущий активный фрагмент:
public abstract class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
private SparseArray<Fragment> mRegisteredFragments = new SparseArray<>();
public MyFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@NonNull
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mRegisteredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
mRegisteredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return mRegisteredFragments.get(position);
}
}
И, наконец,Фактический адаптер пейджера:
public class ParametersPagerAdapter extends MyFragmentStatePagerAdapter {
private static final String TAG = "ParametersPagerAdapter";
private static ArrayList<RouteStructureParamListItem> mItems;
private AccountsModel mCurrentUser;
private String mToolbarTitle, mToolbarSubtitle;
public ParametersPagerAdapter(FragmentManager fm, ArrayList<RouteStructureParamListItem> items,
AccountsModel user, String toolbarTitle, String toolbarSubtitle) {
super(fm);
mItems = items;
mCurrentUser = user;
mToolbarTitle = toolbarTitle;
mToolbarSubtitle = toolbarSubtitle;
}
@Override
public Fragment getItem(int position) {
RouteStructureParamListItem item = mItems.get(position);
switch (item.getParameterType()) {
case ParameterTypes.Text:
return TextParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.Image:
return ImageParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.GPS:
return GPSParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.Vibration:
return VibParameterFragment.newInstance(item, mCurrentUser, position,
mToolbarTitle, mToolbarSubtitle);
case ParameterTypes.Signature:
return SignatureParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.Date:
return DateTimeParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.Number:
return NumericParameterFragment.newInstance(item, mCurrentUser, position);
case ParameterTypes.Response:
return ResponseParameterFragment.newInstance(item, mCurrentUser, position);
default:
Log.w(TAG, "WARNING: Parameter with type '" + item.getParameterType() + "' is not supported!");
return ParameterFragment.newInstance(item, mCurrentUser, position);
}
}
@Override
public int getCount() {
return mItems.size();
}
}
Я бьюсь уже несколько дней, чтобы понять, что не так.Любая помощь приветствуется.
Спасибо!