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.
This commit is contained in:
Peter Serwylo 2016-11-24 10:44:16 +11:00
parent fff7999aac
commit 55824a491b
4 changed files with 113 additions and 0 deletions

View File

@ -1,6 +1,7 @@
package org.fdroid.fdroid.views.main; package org.fdroid.fdroid.views.main;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
@ -8,6 +9,7 @@ import android.widget.Button;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.views.fragments.PreferencesFragment;
import org.fdroid.fdroid.views.myapps.MyAppsViewBinder; import org.fdroid.fdroid.views.myapps.MyAppsViewBinder;
import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; 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() { public void bindSettingsView() {
activity.getLayoutInflater().inflate(R.layout.main_tab_settings, frame, true);
} }
} }

View File

@ -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();
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.main.SettingsView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</org.fdroid.fdroid.views.main.SettingsView>

View File

@ -2,6 +2,7 @@
<resources> <resources>
<item type="id" name="category_spinner" /> <item type="id" name="category_spinner" />
<item type="id" name="appDetailsSummaryHeader" /> <item type="id" name="appDetailsSummaryHeader" />
<item type="id" name="preference_fragment_parent" />
<item type="id" name="whats_new_feature" /> <item type="id" name="whats_new_feature" />
<item type="id" name="whats_new_large_tile" /> <item type="id" name="whats_new_large_tile" />