From 55824a491b2f0c84cbbc56dc43daa0ea0fd7fb6f Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 24 Nov 2016 10:44:16 +1100 Subject: [PATCH] Settings: Added preference fragment to the last tab in the main view. This is a little bit flakey at this point, because the weird asynchronous nature of adding fragments. If swiping to the second-to-last entry on the bottom navigation view, it will populate the settings fragment in the UI and then it will dissapear. Need to fix this. --- .../fdroid/views/main/MainViewController.java | 16 ++++ .../fdroid/views/main/SettingsView.java | 89 +++++++++++++++++++ app/src/main/res/layout/main_tab_settings.xml | 7 ++ app/src/main/res/values/ids.xml | 1 + 4 files changed, 113 insertions(+) create mode 100644 app/src/main/java/org/fdroid/fdroid/views/main/SettingsView.java create mode 100644 app/src/main/res/layout/main_tab_settings.xml diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainViewController.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainViewController.java index 234a6ebe4..d67ca6f2b 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainViewController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainViewController.java @@ -1,6 +1,7 @@ package org.fdroid.fdroid.views.main; import android.content.Intent; +import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.view.View; @@ -8,6 +9,7 @@ import android.widget.Button; import android.widget.FrameLayout; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.views.fragments.PreferencesFragment; import org.fdroid.fdroid.views.myapps.MyAppsViewBinder; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; @@ -72,6 +74,20 @@ class MainViewController extends RecyclerView.ViewHolder { }); } + /** + * Attaches a {@link PreferencesFragment} to the view. Everything else is managed by the + * fragment itself, so no further work needs to be done by this view binder. + * + * Note: It is tricky to attach a {@link Fragment} to a view from this view holder. This is due + * to the way in which the {@link RecyclerView} will reuse existing views and ask us to + * put a settings fragment in there at arbitrary times. Usually it wont be the same view we + * attached the fragment to last time, which causes weirdness. The solution is to use code from + * the com.lsjwzh.widget.recyclerviewpager.FragmentStatePagerAdapter which manages this. + * The code has been ported to {@link SettingsView}. + * + * @see SettingsView + */ public void bindSettingsView() { + activity.getLayoutInflater().inflate(R.layout.main_tab_settings, frame, true); } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/SettingsView.java b/app/src/main/java/org/fdroid/fdroid/views/main/SettingsView.java new file mode 100644 index 000000000..afd8f2121 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/main/SettingsView.java @@ -0,0 +1,89 @@ +package org.fdroid.fdroid.views.main; + +import android.annotation.TargetApi; +import android.content.Context; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +import org.fdroid.fdroid.R; +import org.fdroid.fdroid.views.fragments.PreferencesFragment; + +/** + * When attached to the window, the {@link PreferencesFragment} will be added. When detached from + * the window, the fragment will be removed. + * + * Based on code from https://github.com/lsjwzh/RecyclerViewPager/blob/master/lib/src/main/java/com/lsjwzh/widget/recyclerviewpager/FragmentStatePagerAdapter.java + * licensed under the Apache 2.0 license (https://github.com/lsjwzh/RecyclerViewPager/blob/master/LICENSE). + * @see android.support.v4.app.FragmentStatePagerAdapter Much of the code here was ported from this class. + */ +public class SettingsView extends FrameLayout { + + private FragmentTransaction currentTransaction; + + public SettingsView(Context context) { + super(context); + setId(R.id.preference_fragment_parent); + } + + public SettingsView(Context context, AttributeSet attrs) { + super(context, attrs); + setId(R.id.preference_fragment_parent); + } + + public SettingsView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setId(R.id.preference_fragment_parent); + } + + @TargetApi(21) + public SettingsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setId(R.id.preference_fragment_parent); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + AppCompatActivity activity = (AppCompatActivity) getContext(); + if (activity == null) { + throw new IllegalArgumentException("Cannot add a SettingsView to activities which are not an AppCompatActivity"); + } + + if (currentTransaction == null) { + currentTransaction = activity.getSupportFragmentManager().beginTransaction(); + } + + currentTransaction.replace(getId(), new PreferencesFragment(), "preferences-fragment"); + currentTransaction.commitAllowingStateLoss(); + currentTransaction = null; + activity.getSupportFragmentManager().executePendingTransactions(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + AppCompatActivity activity = (AppCompatActivity) getContext(); + if (activity == null) { + throw new IllegalArgumentException("Cannot add a SettingsView to activities which are not an AppCompatActivity"); + } + + Fragment existingFragment = activity.getSupportFragmentManager().findFragmentByTag("preferences-fragment"); + if (existingFragment == null) { + return; + } + + if (currentTransaction == null) { + currentTransaction = activity.getSupportFragmentManager().beginTransaction(); + } + currentTransaction.remove(existingFragment); + currentTransaction.commitAllowingStateLoss(); + currentTransaction = null; + activity.getSupportFragmentManager().executePendingTransactions(); + } + +} diff --git a/app/src/main/res/layout/main_tab_settings.xml b/app/src/main/res/layout/main_tab_settings.xml new file mode 100644 index 000000000..97d338420 --- /dev/null +++ b/app/src/main/res/layout/main_tab_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index c2fc8ac10..46c7bf804 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -2,6 +2,7 @@ +