diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
index de68269e9..e1b61ea7c 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
@@ -1,6 +1,16 @@
package org.schabi.newpipe.fragments;
+import static android.widget.RelativeLayout.ABOVE;
+import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
+import static android.widget.RelativeLayout.ALIGN_PARENT_TOP;
+import static android.widget.RelativeLayout.BELOW;
+import static com.google.android.material.tabs.TabLayout.INDICATOR_GRAVITY_BOTTOM;
+import static com.google.android.material.tabs.TabLayout.INDICATOR_GRAVITY_TOP;
+
import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -9,7 +19,9 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
@@ -17,6 +29,7 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
import androidx.preference.PreferenceManager;
+import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
@@ -29,6 +42,8 @@ import org.schabi.newpipe.settings.tabs.Tab;
import org.schabi.newpipe.settings.tabs.TabsManager;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
+import org.schabi.newpipe.util.ThemeHelper;
+import org.schabi.newpipe.views.ScrollableTabLayout;
import java.util.ArrayList;
import java.util.List;
@@ -42,8 +57,11 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
private boolean hasTabsChanged = false;
- private boolean previousYoutubeRestrictedModeEnabled;
+ private SharedPreferences prefs;
+ private boolean youtubeRestrictedModeEnabled;
private String youtubeRestrictedModeEnabledKey;
+ private boolean mainTabsPositionBottom;
+ private String mainTabsPositionKey;
/*//////////////////////////////////////////////////////////////////////////
// Fragment's LifeCycle
@@ -66,10 +84,11 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
}
});
+ prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
- previousYoutubeRestrictedModeEnabled =
- PreferenceManager.getDefaultSharedPreferences(requireContext())
- .getBoolean(youtubeRestrictedModeEnabledKey, false);
+ youtubeRestrictedModeEnabled = prefs.getBoolean(youtubeRestrictedModeEnabledKey, false);
+ mainTabsPositionKey = getString(R.string.main_tabs_position_key);
+ mainTabsPositionBottom = prefs.getBoolean(mainTabsPositionKey, false);
}
@Override
@@ -87,25 +106,27 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
binding.mainTabLayout.setupWithViewPager(binding.pager);
binding.mainTabLayout.addOnTabSelectedListener(this);
- binding.mainTabLayout.setTabRippleColor(binding.mainTabLayout.getTabRippleColor()
- .withAlpha(32));
setupTabs();
+ updateTabLayoutPosition();
}
@Override
public void onResume() {
super.onResume();
- final boolean youtubeRestrictedModeEnabled =
- PreferenceManager.getDefaultSharedPreferences(requireContext())
- .getBoolean(youtubeRestrictedModeEnabledKey, false);
- if (previousYoutubeRestrictedModeEnabled != youtubeRestrictedModeEnabled) {
- previousYoutubeRestrictedModeEnabled = youtubeRestrictedModeEnabled;
- setupTabs();
- } else if (hasTabsChanged) {
+ final boolean newYoutubeRestrictedModeEnabled =
+ prefs.getBoolean(youtubeRestrictedModeEnabledKey, false);
+ if (youtubeRestrictedModeEnabled != newYoutubeRestrictedModeEnabled || hasTabsChanged) {
+ youtubeRestrictedModeEnabled = newYoutubeRestrictedModeEnabled;
setupTabs();
}
+
+ final boolean newMainTabsPosition = prefs.getBoolean(mainTabsPositionKey, false);
+ if (mainTabsPositionBottom != newMainTabsPosition) {
+ mainTabsPositionBottom = newMainTabsPosition;
+ updateTabLayoutPosition();
+ }
}
@Override
@@ -190,6 +211,38 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
setTitle(tabsList.get(tabPosition).getTabName(requireContext()));
}
+ private void updateTabLayoutPosition() {
+ final ScrollableTabLayout tabLayout = binding.mainTabLayout;
+ final ViewPager viewPager = binding.pager;
+ final boolean bottom = mainTabsPositionBottom;
+
+ // change layout params to make the tab layout appear either at the top or at the bottom
+ final var tabParams = (RelativeLayout.LayoutParams) tabLayout.getLayoutParams();
+ final var pagerParams = (RelativeLayout.LayoutParams) viewPager.getLayoutParams();
+
+ tabParams.removeRule(bottom ? ALIGN_PARENT_TOP : ALIGN_PARENT_BOTTOM);
+ tabParams.addRule(bottom ? ALIGN_PARENT_BOTTOM : ALIGN_PARENT_TOP);
+ pagerParams.removeRule(bottom ? BELOW : ABOVE);
+ pagerParams.addRule(bottom ? ABOVE : BELOW, R.id.main_tab_layout);
+ tabLayout.setSelectedTabIndicatorGravity(
+ bottom ? INDICATOR_GRAVITY_TOP : INDICATOR_GRAVITY_BOTTOM);
+
+ tabLayout.setLayoutParams(tabParams);
+ viewPager.setLayoutParams(pagerParams);
+
+ // change the background and icon color of the tab layout:
+ // service-colored at the top, app-background-colored at the bottom
+ tabLayout.setBackgroundColor(ThemeHelper.resolveColorFromAttr(requireContext(),
+ bottom ? R.attr.colorSecondary : R.attr.colorPrimary));
+
+ @ColorInt final int iconColor = bottom
+ ? ThemeHelper.resolveColorFromAttr(requireContext(), R.attr.colorAccent)
+ : Color.WHITE;
+ tabLayout.setTabRippleColor(ColorStateList.valueOf(iconColor).withAlpha(32));
+ tabLayout.setTabIconTint(ColorStateList.valueOf(iconColor));
+ tabLayout.setSelectedTabIndicatorColor(iconColor);
+ }
+
@Override
public void onTabSelected(final TabLayout.Tab selectedTab) {
if (DEBUG) {
diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml
index 70f129561..a846b3829 100644
--- a/app/src/main/res/values/settings_keys.xml
+++ b/app/src/main/res/values/settings_keys.xml
@@ -270,6 +270,9 @@
caption_settings_key
caption_user_set_key
+
+ main_tabs_position
+
show_search_suggestions
show_local_search_suggestions
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index eb774f338..47e5048e5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -222,6 +222,8 @@
Delete entire search history?
Search history deleted
Fast mode
+ Move main tab selector to the bottom
+ Main tabs position
Error
External storage unavailable
diff --git a/app/src/main/res/xml/appearance_settings.xml b/app/src/main/res/xml/appearance_settings.xml
index d726e26b7..beb46cdf5 100644
--- a/app/src/main/res/xml/appearance_settings.xml
+++ b/app/src/main/res/xml/appearance_settings.xml
@@ -66,4 +66,12 @@
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
+
+